home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / share / gtk-2.0 / demo / pixbufs.c < prev    next >
Encoding:
C/C++ Source or Header  |  2006-04-25  |  6.1 KB  |  272 lines

  1. /* Pixbufs
  2.  *
  3.  * A GdkPixbuf represents an image, normally in RGB or RGBA format.
  4.  * Pixbufs are normally used to load files from disk and perform
  5.  * image scaling.
  6.  *
  7.  * This demo is not all that educational, but looks cool. It was written
  8.  * by Extreme Pixbuf Hacker Federico Mena Quintero. It also shows
  9.  * off how to use GtkDrawingArea to do a simple animation.
  10.  *
  11.  * Look at the Image demo for additional pixbuf usage examples.
  12.  *
  13.  */
  14.  
  15. #include <stdlib.h>
  16. #include <gtk/gtk.h>
  17. #include <math.h>
  18.  
  19. #include "demo-common.h"
  20.  
  21. #define FRAME_DELAY 50
  22.  
  23. #define BACKGROUND_NAME "background.jpg"
  24.  
  25. static const char *image_names[] = {
  26.   "apple-red.png",
  27.   "gnome-applets.png",
  28.   "gnome-calendar.png",
  29.   "gnome-foot.png",
  30.   "gnome-gmush.png",
  31.   "gnome-gimp.png",
  32.   "gnome-gsame.png",
  33.   "gnu-keys.png"
  34. };
  35.  
  36. #define N_IMAGES G_N_ELEMENTS (image_names)
  37.  
  38. /* demo window */
  39. static GtkWidget *window = NULL;
  40.  
  41. /* Current frame */
  42. static GdkPixbuf *frame;
  43.  
  44. /* Background image */
  45. static GdkPixbuf *background;
  46. static gint back_width, back_height;
  47.  
  48. /* Images */
  49. static GdkPixbuf *images[N_IMAGES];
  50.  
  51. /* Widgets */
  52. static GtkWidget *da;
  53.  
  54. /* Loads the images for the demo and returns whether the operation succeeded */
  55. static gboolean
  56. load_pixbufs (GError **error)
  57. {
  58.   gint i;
  59.   char *filename;
  60.  
  61.   if (background)
  62.     return TRUE; /* already loaded earlier */
  63.  
  64.   /* demo_find_file() looks in the the current directory first,
  65.    * so you can run gtk-demo without installing GTK, then looks
  66.    * in the location where the file is installed.
  67.    */
  68.   filename = demo_find_file (BACKGROUND_NAME, error);
  69.   if (!filename)
  70.     return FALSE; /* note that "error" was filled in and returned */
  71.  
  72.   background = gdk_pixbuf_new_from_file (filename, error);
  73.   g_free (filename);
  74.   
  75.   if (!background)
  76.     return FALSE; /* Note that "error" was filled with a GError */
  77.  
  78.   back_width = gdk_pixbuf_get_width (background);
  79.   back_height = gdk_pixbuf_get_height (background);
  80.  
  81.   for (i = 0; i < N_IMAGES; i++)
  82.     {
  83.       filename = demo_find_file (image_names[i], error);
  84.       if (!filename)
  85.     return FALSE; /* Note that "error" was filled with a GError */
  86.       
  87.       images[i] = gdk_pixbuf_new_from_file (filename, error);
  88.       g_free (filename);
  89.       
  90.       if (!images[i])
  91.     return FALSE; /* Note that "error" was filled with a GError */
  92.     }
  93.  
  94.   return TRUE;
  95. }
  96.  
  97. /* Expose callback for the drawing area */
  98. static gint
  99. expose_cb (GtkWidget      *widget,
  100.        GdkEventExpose *event,
  101.        gpointer       data)
  102. {
  103.   guchar *pixels;
  104.   int rowstride;
  105.  
  106.   rowstride = gdk_pixbuf_get_rowstride (frame);
  107.  
  108.   pixels = gdk_pixbuf_get_pixels (frame) + rowstride * event->area.y + event->area.x * 3;
  109.  
  110.   gdk_draw_rgb_image_dithalign (widget->window,
  111.                 widget->style->black_gc,
  112.                 event->area.x, event->area.y,
  113.                 event->area.width, event->area.height,
  114.                 GDK_RGB_DITHER_NORMAL,
  115.                 pixels, rowstride,
  116.                 event->area.x, event->area.y);
  117.  
  118.   return TRUE;
  119. }
  120.  
  121. #define CYCLE_LEN 60
  122.  
  123. static int frame_num;
  124.  
  125. /* Timeout handler to regenerate the frame */
  126. static gint
  127. timeout (gpointer data)
  128. {
  129.   double f;
  130.   int i;
  131.   double xmid, ymid;
  132.   double radius;
  133.  
  134.   gdk_pixbuf_copy_area (background, 0, 0, back_width, back_height,
  135.             frame, 0, 0);
  136.  
  137.   f = (double) (frame_num % CYCLE_LEN) / CYCLE_LEN;
  138.  
  139.   xmid = back_width / 2.0;
  140.   ymid = back_height / 2.0;
  141.  
  142.   radius = MIN (xmid, ymid) / 2.0;
  143.  
  144.   for (i = 0; i < N_IMAGES; i++)
  145.     {
  146.       double ang;
  147.       int xpos, ypos;
  148.       int iw, ih;
  149.       double r;
  150.       GdkRectangle r1, r2, dest;
  151.       double k;
  152.  
  153.       ang = 2.0 * G_PI * (double) i / N_IMAGES - f * 2.0 * G_PI;
  154.  
  155.       iw = gdk_pixbuf_get_width (images[i]);
  156.       ih = gdk_pixbuf_get_height (images[i]);
  157.  
  158.       r = radius + (radius / 3.0) * sin (f * 2.0 * G_PI);
  159.  
  160.       xpos = floor (xmid + r * cos (ang) - iw / 2.0 + 0.5);
  161.       ypos = floor (ymid + r * sin (ang) - ih / 2.0 + 0.5);
  162.  
  163.       k = (i & 1) ? sin (f * 2.0 * G_PI) : cos (f * 2.0 * G_PI);
  164.       k = 2.0 * k * k;
  165.       k = MAX (0.25, k);
  166.  
  167.       r1.x = xpos;
  168.       r1.y = ypos;
  169.       r1.width = iw * k;
  170.       r1.height = ih * k;
  171.  
  172.       r2.x = 0;
  173.       r2.y = 0;
  174.       r2.width = back_width;
  175.       r2.height = back_height;
  176.  
  177.       if (gdk_rectangle_intersect (&r1, &r2, &dest))
  178.     gdk_pixbuf_composite (images[i],
  179.                   frame,
  180.                   dest.x, dest.y,
  181.                   dest.width, dest.height,
  182.                   xpos, ypos,
  183.                   k, k,
  184.                   GDK_INTERP_NEAREST,
  185.                   ((i & 1)
  186.                    ? MAX (127, fabs (255 * sin (f * 2.0 * G_PI)))
  187.                    : MAX (127, fabs (255 * cos (f * 2.0 * G_PI)))));
  188.     }
  189.  
  190.   gtk_widget_queue_draw (da);
  191.  
  192.   frame_num++;
  193.   return TRUE;
  194. }
  195.  
  196. static guint timeout_id;
  197.  
  198. static void
  199. cleanup_callback (GtkObject *object,
  200.           gpointer   data)
  201. {
  202.   g_source_remove (timeout_id);
  203.   timeout_id = 0;
  204. }
  205.  
  206. GtkWidget *
  207. do_pixbufs (GtkWidget *do_widget)
  208. {
  209.   if (!window)
  210.     {
  211.       GError *error;
  212.  
  213.       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  214.       gtk_window_set_screen (GTK_WINDOW (window),
  215.                  gtk_widget_get_screen (do_widget));
  216.       gtk_window_set_title (GTK_WINDOW (window), "Pixbufs");
  217.       gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
  218.  
  219.       g_signal_connect (window, "destroy", G_CALLBACK (gtk_widget_destroyed), &window);
  220.       g_signal_connect (window, "destroy", G_CALLBACK (cleanup_callback), NULL);
  221.  
  222.  
  223.       error = NULL;
  224.       if (!load_pixbufs (&error))
  225.     {
  226.       GtkWidget *dialog;
  227.  
  228.       dialog = gtk_message_dialog_new (GTK_WINDOW (window),
  229.                        GTK_DIALOG_DESTROY_WITH_PARENT,
  230.                        GTK_MESSAGE_ERROR,
  231.                        GTK_BUTTONS_CLOSE,
  232.                        "Failed to load an image: %s",
  233.                        error->message);
  234.  
  235.       g_error_free (error);
  236.  
  237.       g_signal_connect (dialog, "response",
  238.                 G_CALLBACK (gtk_widget_destroy), NULL);
  239.  
  240.       gtk_widget_show (dialog);
  241.     }
  242.       else
  243.     {
  244.       gtk_widget_set_size_request (window, back_width, back_height);
  245.  
  246.       frame = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, back_width, back_height);
  247.  
  248.       da = gtk_drawing_area_new ();
  249.  
  250.       g_signal_connect (da, "expose_event",
  251.                 G_CALLBACK (expose_cb), NULL);
  252.  
  253.       gtk_container_add (GTK_CONTAINER (window), da);
  254.  
  255.       timeout_id = g_timeout_add (FRAME_DELAY, timeout, NULL);
  256.     }
  257.     }
  258.  
  259.   if (!GTK_WIDGET_VISIBLE (window))
  260.     {
  261.       gtk_widget_show_all (window);
  262.     }
  263.   else
  264.     {
  265.       gtk_widget_destroy (window);
  266.       window = NULL;
  267.       g_object_unref (frame);
  268.     }
  269.  
  270.   return window;
  271. }
  272.